<template>
  <div class="material-lab">
    <!-- 控制面板 -->
    <div class="controls">
      <el-form label-width="80px">
        <el-form-item label="几何体">
          <el-select v-model="shape" @change="updateGeometry">
            <el-option label="立方体 Box" value="box" />
            <el-option label="球体 Sphere" value="sphere" />
            <el-option label="圆环 Torus" value="torus" />
            <el-option label="圆锥 Cone" value="cone" />
          </el-select>
        </el-form-item>

        <el-form-item label="材质">
          <el-select v-model="materialType" @change="updateMaterial">
            <el-option label="Basic 材质" value="basic" />
            <el-option label="Standard 材质" value="standard" />
            <el-option label="Phong 材质" value="phong" />
          </el-select>
        </el-form-item>

        <el-form-item label="线框模式">
          <el-switch v-model="wireframe" @change="updateMaterial" />
        </el-form-item>
      </el-form>
    </div>
    <div ref="container" class="three-canvas"></div>
  </div>
</template>

<script setup>
import { onMounted, ref } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

const container = ref(null);
let scene, camera, renderer, controls, mesh;
// 控制面板参数
const shape = ref("box");
const materialType = ref("standard");
const wireframe = ref(false);

function initScene() {
  // 1. 创建场景 Scene：三维世界的容器
  scene = new THREE.Scene();

  // 2. 创建相机 Camera：观察视角（透视相机模拟人眼）
  camera = new THREE.PerspectiveCamera(
    75, // 视野角度（越大越广）
    window.innerWidth / window.innerHeight, // 宽高比
    0.1, // 最近可视距离
    1000 // 最远可视距离
  );
  camera.position.set(0, 1.5, 4);

  // 3. 创建渲染器 Renderer：将场景渲染到 canvas 上
  renderer = new THREE.WebGLRenderer({ antialias: true }); // 抗锯齿
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.value.appendChild(renderer.domElement);

  // 4. 创建几何体 + 材质 + 网格 Mesh（组成一个可见物体）
  //   const geometry = new THREE.BoxGeometry(); // 创建立方体几何体
  //   const material = new THREE.MeshStandardMaterial({ color: 0xff0000 }); // 红色，受光照影响
  //   const cube = new THREE.Mesh(geometry, material);
  //   scene.add(cube); // 添加到场景中

  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;

  // 5. 添加坐标轴辅助器 AxesHelper
  const axesHelper = new THREE.AxesHelper(5); // X红 Y绿 Z蓝
  scene.add(axesHelper);

  // 6. 添加光源（模型不再全黑）
  const ambient = new THREE.AmbientLight(0x404040);
  const directional = new THREE.DirectionalLight(0xffffff, 1);
  directional.position.set(2, 4, 3);
  scene.add(ambient, directional);
}

function updateGeometry() {
  const geometryMap = {
    box: new THREE.BoxGeometry(),
    sphere: new THREE.SphereGeometry(0.75, 32, 32),
    torus: new THREE.TorusGeometry(0.6, 0.2, 16, 100),
    cone: new THREE.ConeGeometry(0.6, 1.2, 32),
  };

  const geometry = geometryMap[shape.value];
  // 清理旧网格
  if (mesh) {
    scene.remove(mesh); // 从场景移除
    mesh.geometry.dispose(); // 释放几何体资源
  }
  // 创建新网格
  mesh = new THREE.Mesh(geometry, createMaterial());
  scene.add(mesh);
}

function updateMaterial() {
  if (!mesh) return;
  mesh.material.dispose(); // 释放旧材质资源, dispose,Three.js 中释放材质资源的关键API，防止内存累积
  mesh.material = createMaterial();
}

function createMaterial() {
  const base = {
    color: 0x00aaff,
    wireframe: wireframe.value, // 线框模式开关
  };
  switch (materialType.value) {
    case "basic":
      return new THREE.MeshBasicMaterial(base); // 基础材质
    case "standard":
      return new THREE.MeshStandardMaterial({
        // PBR标准材质
        ...base,
        metalness: 0.4, // 金属质感 (0-1)
        roughness: 0.6, // 表面粗糙度 (0-1)
      });
    case "phong":
      return new THREE.MeshPhongMaterial({ ...base, shininess: 100 }); // 光泽材质  shininess高光强度
  }
}
function animate() {
  requestAnimationFrame(animate);
  if (mesh) {
    mesh.rotation.x += 0.01;
    mesh.rotation.y += 0.01;
  }
  controls.update();
  renderer.render(scene, camera);
}

onMounted(() => {
  initScene();
  updateGeometry();
  updateMaterial();
  animate();
});
</script>

<style scoped>
.material-lab {
  display: flex;
  padding: 20px;
}
.controls {
  width: 220px;
  margin-right: 20px;
}
.three-canvas {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
</style>
